/*
 * (c) ralfoide, http://gamez.googlecode.com/, 2008
 * Project: gamez
 * License TBD
 */


package com.alfray.gamez.shape;

import javax.microedition.khronos.opengles.GL10;


//-----------------------------------------------

/**
 * The 3d square plate.
 */
public class Flag extends Shape {

	private int mNumSegment;
	private int[] xPrecalc;

	/**
	 * Creates a "flag" shape with triangles.
	 * Flat on Z=0 plane, with X=[-0.5 => 0.5], Y=[-0.5, 0.5]
	 * with num_seg segments in X and Y (min 1.)
	 */
    public Flag(int num_seg, Color color, boolean checkerboard) {
        
    	mNumSegment = num_seg;
    	assert num_seg <= 254;
    	
        /*
         *   X: seg: 0..nx-1 => 0..1 => w=1/nx (0 to nx-1 + last on nx)
         *   vertex on x: nx+1
         *   number of triangles: nx*ny*2
         *   
         *   vertex indices (e.g nx=5, ny=5)
         *   ...
         *   5 6 7 8 9 10
         *   0 1 2 3 4 5
         *   
         *   view from top:
         *   5 --- 6  5-6-1
         *   | \   |
         *   |  \  |
         *   |   \ |
         *   0 --- 1  0-5-1
         *   triangles in CW: 0 5 1 + 5 6 1
         *   i.e. i,j i,j+1 i+1,j + i,j+1 i+1,j+1 i+1,j
         */
    	final int nn = num_seg;

        final float[] vertices = new float[(nn+1)*(nn+1)*3];
        final float[] normals = new float[(nn+1)*(nn+1)*3];
        final float[] textCoord = new float[(nn+1)*(nn+1)*2];
        final float nn1 = 1.0f/nn;
        
        for (int j = 0; j <= nn; ++j) {
        	for (int i = 0; i <= nn; ++i) {
        		int k = i + j*(nn+1);
        		int k3 = k * 3;
        		vertices[k3+0] = (nn1*i) - 0.5f; // x
        		vertices[k3+1] = (nn1*j) - 0.5f; // y
        		vertices[k3+2] = 0.0f; // z

        		// (note: not normalized)
        		normals[k3+0] = (nn1*i) * 2.0f - 1.0f; // x
        		normals[k3+1] = (nn1*j) * 2.0f - 1.0f; // y
        		normals[k3+2] = 1.0f; // z

        		textCoord[k*2+0] = (nn1*i); // x
        		textCoord[k*2+1] = 1 - (nn1*j); // y
        	}
        }
        
        final short[] indices = new short[nn*nn*2*3/(checkerboard ? 2 : 1)];
        for (int k = 0, j = 0; j < nn; ++j) {
        	for (int i = 0; i < nn; ++i) {
        		int b = (i + j*(nn+1));
        		if (checkerboard && (((i+j)&1) == 0)) continue;
                // triangles: i,j i,j+1 i+1,j + i,j+1 i+1,j+1 i+1,j
        		indices[k+0] = (short)(b+0        );
        		indices[k+1] = (short)(b+0 + nn+1 );
        		indices[k+2] = (short)(b+1        );
        		indices[k+3] = (short)(b+0 + nn+1 );
        		indices[k+4] = (short)(b+1 + nn+1 );
        		indices[k+5] = (short)(b+1        );
        		k += 6;
        	}
        }
        
        final float diffuse[] = getColor(color);

        setupBuffers(vertices, normals, diffuse, indices);
		setupTextBuffers(textCoord);
		setUseTextureUnit(0);

        int nn8 = nn*8+8;
        double nn81 = 1.0/nn8;
        xPrecalc = new int[nn8];
        for (int i = 0; i < nn8; i++) {
        	xPrecalc[i] = (int)(65536.0 * Math.cos(Math.PI*2 * i*nn81));
        }
    }

    /**
     * Override drawTo rotate the object.
     */
    @Override
    public void drawTo(GL10 gl) {
        super.drawTo(gl);
    }

	public void animate(long ms_since_start) {

		final int nn = mNumSegment;
    	final int nn8 = nn*8+8;
    	
    	int ax = ((int) (ms_since_start >> 6)) % nn8;
    	int ay = ((int) (ms_since_start >> 3)) % nn8;
    	int ex = nn8 + ax;
    	int ey = nn8 + ay;

    	int amp = (int) ((ms_since_start >> 6) & 0x1FF);
    	if (amp > 0xFF) amp = 0x1FF-amp;
    	
        final int[] p = xPrecalc;
        int offset = 2;
        for (int j = ay; j < ey; j+=8) {
        	int v = p[j - (j>=nn8 ? nn8 : 0)];
            synchronized(xVertexBuffer) {
            	for (int i = ax; i < ex; i+=8, offset += 3) {
                	int u = p[i - (i>=nn8 ? nn8 : 0)];
                	int k = ((u+v)*amp) >> 8;

                	xVertexBuffer.position(offset);
                	xVertexBuffer.put(k);
                	xVertexBuffer.position(0);
            	}
            }

        }
	}

}

